package ms.jasim.console.gui;

import java.awt.BorderLayout;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;

import javax.swing.SwingUtilities;

import ms.jacrim.framework.ActiveSolution;
import ms.jacrim.framework.Configuration;
import ms.jacrim.framework.ActiveSolution.ActionInfo;
import ms.jacrim.pddl.PddlSolution;
import ms.jacrim.pddl.PddlSolution.Functor;
import ms.jacrim.tropos.UID;
import ms.jasim.console.JasimClientListener;
import ms.spm.IAppContext;
import ms.utils.ExceptionUtil;
import chrriis.dj.nativeswing.swtimpl.components.JWebBrowser;
import chrriis.dj.nativeswing.swtimpl.components.WebBrowserAdapter;
import chrriis.dj.nativeswing.swtimpl.components.WebBrowserEvent;

import com.vlsolutions.swing.docking.DockKey;

public class ActiveSolutionDockPane extends DefaultDockPane {

	private static final String GOAL_SATISFYING_CMDS = " <a href=\"command://fulfill $goal$\" class=\"button\">fulfill</a> <a href=\"command://fail satisfies($actor$,$goal$)\" class=\"button\">fail</a>";

	private static final long serialVersionUID = 1L;

	private String webTemplate, executingTemplate, finishedTemplate, pendingTemplate;
	private JWebBrowser wb;
	private SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");

	private String htmlContent;

	public ActiveSolutionDockPane(IAppContext context) {
		super(context);
		wb = new JWebBrowser(JWebBrowser.destroyOnFinalization());
		wb.setMenuBarVisible(false);
		wb.setBarsVisible(false);
		wb.setStatusBarVisible(false);
		add(wb, BorderLayout.CENTER);
		wb.navigate("about:blank");
		// refresh();
		wb.addWebBrowserListener(new WebBrowserAdapter() {
			@Override
			public void commandReceived(WebBrowserEvent e, String command, String[] args) {
				try {
					svcJasim.sendCommand(command);
				} catch (IOException e1) {
				}
			}
		});
	}

	@Override
	protected DockKey createDocKey() {
		DockKey key = new DockKey(this.getClass().getName(), "Active Solution", "", null, null);
		key.setMaximizeEnabled(true);
		key.setAutoHideEnabled(true);
		key.setCloseEnabled(true);
		return key;
	}

	@Override
	protected void setupContext() {
		super.setupContext();

		Configuration cfg = context.getService(Configuration.class);
		String templateFile = "resources/actsolution.html";
		templateFile = cfg.get("solution_web_template", templateFile);

		try {
			webTemplate = getContents(templateFile);
			pendingTemplate = getContents(cfg.get("solution_pending_action", "resources/pending_template.html"));
			executingTemplate = getContents(cfg.get("solution_pending_action", "resources/executing_template.html"));
			finishedTemplate = getContents(cfg.get("solution_pending_action", "resources/finished_template.html"));
		} catch (Exception e) {
			ExceptionUtil.handle(e, context);
		}

		svcJasim.addListener(new JasimClientListener() {
			@Override
			public void notifyListener() {
				refresh();
			}
		});
	}

	// phuong thuc duoc thuc thi trong thread Timer, do do phai goi invoke
	// latter
	private void refresh() {
		ActiveSolution sol = svcJasim.getActiveSolution();
		StringBuilder body = new StringBuilder();
		if (sol != null) {
			for (int i = 0; i < sol.ActionCount(); i++) {
				PddlSolution.Action act = sol.getAction(i);
				ActionInfo info = sol.findActionInfo(act);
				// check whether action is pending or executing or finished
				// if there exists an ActionInfo associated with a action,
				// the action is in execution or already finished.
				if (info != null) {
					String template = info.getEnd() != null ? finishedTemplate : executingTemplate;
					String panelID = UID.generate().toString();
					template = template.replace("$action_name$", act.toString()).replace("$div_uid$", panelID);
					String timeInfo = "Start: " + sdf.format(info.getStart());
					if (info.getEnd() != null)
						timeInfo += ", End: " + sdf.format(info.getEnd());
					else if (act.getFunctor() == Functor.SATISFIES)
						timeInfo += GOAL_SATISFYING_CMDS.replace("$goal$", act.Argument(1).toLowerCase()).replace("$actor$",
								act.Argument(0).toLowerCase());
					body.append(template.replace("$action_info$", timeInfo));
				} else {
					body.append(pendingTemplate.replace("$action_name$", act.toString()));
				}
				body.append("\n");
			}
		}
		htmlContent = webTemplate.replace("<!--ACTIONS-->", body.toString());
		SwingUtilities.invokeLater(new Runnable() {

			@Override
			public void run() {
				wb.setHTMLContent(htmlContent);
			}

		});

	}

	static public String getContents(String fileName) throws IOException {
		// ...checks on aFile are elided
		StringBuilder contents = new StringBuilder();

		// use buffering, reading one line at a time
		// FileReader always assumes default encoding is OK!
		BufferedReader input = new BufferedReader(new FileReader(fileName));
		try {
			String line = null; // not declared within while loop
			/*
			 * readLine is a bit quirky : it returns the content of a line MINUS
			 * the newline. it returns null only for the END of the stream. it
			 * returns an empty String if two newlines appear in a row.
			 */
			while ((line = input.readLine()) != null) {
				contents.append(line);
				contents.append(System.getProperty("line.separator"));
			}
		} finally {
			input.close();
		}

		return contents.toString();
	}
}
